using System.Web;
using System.Xml;
using System;

/*	-----------------------------------------------------------------------	
	Copyright:	umlungu consulting (pty) ltd
	Author:		Alan Benington	
	Started:	2007-08-14	
	Status:		release	
	Version:	2.0.0
	Build:		20070806
	License:	GNU General Public License
	-----------------------------------------------------------------------	*/

/*	-----------------------------------------------------------------------	
	Development Notes:
	==================
	20070814:	Starting point with login checking
	-----------------------------------------------------------------------	*/

namespace umlungu.engineX.blogX {
	/// <summary>
	/// The profileX class.
	/// <para>Purpose: This class is used to display a html page within a profiled website.</para>
	/// <para> - It is derived from displayX for basic page display (minus profiled display functionality)</para>
	/// <para> - This class deals with applying basic profiling (eg login and menu control).</para>
	/// <para></para>
	/// </summary>
	public class profileX : displayX {
		#region Invisible properties
		#endregion

		#region Constants
		private const string DESTINATION_LINK = "DestinationLink";
		private const string IPASSPORT_TOKEN = "PXToken";
		#endregion

		#region Visible properties
		/// <summary>The user's iPassport Token</summary>
		/// <value>A token obtained from the iPassport authentication system at Login</value>
		public string Token {
			get { return (UserProfile.Get(IPASSPORT_TOKEN) == null) ? "" : UserProfile.Get(IPASSPORT_TOKEN).InnerText; }
		}
		#endregion

		#region Constructors/Destructors
		/// <overloads>Constructor</overloads>
		/// <summary>Default constructor</summary>
		public profileX() : this("profileX") {
		}
		/// <summary>Constructor for derived classes</summary>
		public profileX(string label) : base(label) {
		}
		#endregion

		#region Public methods
		#endregion

		#region Protected methods
		/// <summary>Initialises the page, including login control</summary>
		protected override void _Initialise() {
			base._Initialise();
			checkLogin();
		}
		/// <summary>
		/// Loads the content xml
		/// </summary>
		protected override void _ProcessRequest() {
			Debugger.Spoor("profileX._ProcessRequest");
			base._ProcessRequest(false);	// ie no default brokers for this class
			checkPattern(true);
		}
		/// <summary>
		/// Post-processes the content for profiling (menus/links at this stage).
		/// NB this is done by calling the base method so that form fields and includes are done first.
		/// </summary>
		protected override void _PostProcessContent() {
			base._PostProcessContent();
			checkPattern();	// check again - broker might have changed patterns
			processMenus();
			TemplateArguments.AddParam("token", "", Token);
		}
		#endregion

		#region Private methods
		/// <summary>Check for login required and re-direct if not already logged in</summary>
		/// <remarks>Note:
		/// <para>The initial link is stored to a user profile value DESTINATION_LINK so that this link can be served post login</para>
		/// <para>At this time the DESTINATION_LINK will not fire a broker process (see login implementation)</para>
		/// </remarks>
		private void checkLogin() {
			Uri thisurl = Request.Url;
			bool isSecure = (Request.ServerVariables["HTTPS"] == "on");

			if (Parameters.Login) {
				UserProfile.Clear(DESTINATION_LINK);
				bool isToken = (Token != "");
				if (isToken) {
					if (!isSecure)
						Response.Redirect(String.Concat("https://", thisurl.Host, thisurl.PathAndQuery));
				} else {
					UserProfile.Add(DESTINATION_LINK, Parameters.LinkName);
					Response.Redirect(String.Concat((isSecure) ? "http://" : "https://", thisurl.Host, thisurl.AbsolutePath, "?link=", Config.LoginLink));
				}
			}
		}
		/// <summary>Check for pattern required in User profile and redirect to (pattern) login page if pattern missing</summary>
		/// <remarks>Note:
		/// <para>Patterns are held in the top most menuitem element that is an ancestor of the menuitem of the current link</para>
		/// </remarks>
		private void checkPattern() {
			checkPattern(false);
		}
		private void checkPattern(bool checkmenu) {
			Uri thisurl = Request.Url;
			bool isSecure = (Request.ServerVariables["HTTPS"] == "on");

			Debugger.Spoor("checkPattern", "Link", Parameters.LinkName);
			if (Parameters.Check) {
				// first check if there is a pattern in the current links menuitem
				string sel = String.Concat("//menuitem[@link='", Parameters.LinkName, "']");
				XmlElement menuitem = Content.SelectSingleNode(sel) as XmlElement;
				if (menuitem != null) {
					Debugger.Spoor("checkPattern", menuitem);
					XmlElement patEl = menuitem.SelectSingleNode("pattern") as XmlElement;
					if (patEl == null) {
						patEl = menuitem.SelectSingleNode("ancestor::menuitem/pattern") as XmlElement;
					}
					if (checkmenu && patEl == null) {	// also check for menu pattern
						patEl = menuitem.SelectSingleNode("ancestor::menu/pattern") as XmlElement;
					}
					if (patEl != null) {
						Debugger.Spoor("checkPattern", patEl);
						if (!UserProfile.TestPattern(patEl)) {
							//Response.Redirect(String.Concat((isSecure) ? "http://" : "https://", thisurl.Host, thisurl.AbsolutePath, "?link=", Config.PatternLink));
							throw new displayException(Config.PatternLink);
						}
					}
				}
			}
			
		}

		///<summary>Remove all men nodes that are set to a pattern that do not match user pattern</summary>
		private void processMenus() {
			Debugger.Spoor("processMenus");
			if (UserProfile.LoginPattern != "") {
				Debugger.Spoor("processMenus", "LoginPattern", UserProfile.LoginPattern);
				foreach (XmlNode menuNode in Content.SelectNodes("//menu[pattern]")) {
					if (!UserProfile.TestPattern(menuNode.SelectSingleNode("pattern") as XmlElement))
						menuNode.ParentNode.RemoveChild(menuNode);
				}
				foreach (XmlNode itmNode in Content.SelectNodes("//menuitem[pattern]")) {
					Debugger.Spoor("processMenus", "itmNode", ((XmlElement)itmNode).GetAttribute("label"));
					if (!UserProfile.TestPattern(itmNode.SelectSingleNode("pattern") as XmlElement))
						itmNode.ParentNode.RemoveChild(itmNode);
				}
			}
		}
		#endregion
	}
}
